#include "../include/KeywordProcessor.h"
#include "../include/DirectoryScanner.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <cctype>
#include <algorithm>

// 使用老师示例中的正确头文件包含方式
#include "cppjieba/Jieba.hpp"
#include "utfcpp/utf8.h"

// 构造函数
KeywordProcessor::KeywordProcessor() : m_tokenizer(cppjieba::Jieba{}),
                                       m_enStopWords(), // 初始化英文停用词集合（空集合）
                                       m_chStopWords()  // 初始化中文停用词集合（空集合）
{                                                       // 加载英文停用词到 m_enStopWords
    load_stopwords("data/en_stopwords.txt", m_enStopWords);
    // 加载中文停用词到 m_chStopWords
    load_stopwords("data/cn_stopwords.txt", m_chStopWords);

    std::cout << "停用词初始化完成：" << std::endl;
    std::cout << "  - 英文停用词数量: " << m_enStopWords.size() << std::endl;
    std::cout << "  - 中文停用词数量: " << m_chStopWords.size() << std::endl;
};

// 加载停用词文件的具体实现
void KeywordProcessor::load_stopwords(const std::string &filename, std::set<std::string> &stopwords)
{
    // 打开停用词文件
    std::ifstream fin(filename);
    if (!fin.is_open())
    {
        std::cerr << "错误：无法打开停用词文件: " << filename << std::endl;
        return;
    }

    std::string word;
    int count = 0;

    // 逐行读取文件内容
    while (std::getline(fin, word))
    {
        // 去除字符串首尾的空白字符
        word.erase(0, word.find_first_not_of(" \t\n\r"));
        word.erase(word.find_last_not_of(" \t\n\r") + 1);

        // 只添加非空的单词到停用词集合中
        if (!word.empty())
        {
            stopwords.insert(word);
            count++;
        }
    }

    // 关闭文件
    fin.close();

    std::cout << "成功加载停用词文件: " << filename
              << ", 加载数量: " << count << std::endl;
}

// 生成英文词典
void KeywordProcessor::create_en_dict(const std::string &dir, const std::string &outfile)
{
    std::cout << "开始生成英文词典..." << std::endl;

    // 1. 扫描目录，获取所有文件名
    auto files = DirectoryScanner::scan(dir);
    if (files.empty())
    {
        std::cerr << "错误：目录 " << dir << " 中没有找到文件" << std::endl;
        return;
    }

    std::map<std::string, int> wordCount; // 存储单词和频率

    // 2. 遍历每个文件
    for (const auto &file : files)
    {
        std::ifstream fin(file);
        if (!fin.is_open())
        {
            std::cerr << "无法打开文件: " << file << std::endl;
            continue;
        }

        std::string word;
        // 3. 按空白字符分割单词
        while (fin >> word)
        {
            std::string cleanWord; // 清洗后的单词

            // 4. 清洗单词：去掉数字和标点符号，只保留字母
            for (char c : word)
            {
                if (std::isalpha(c)) // 只保留字母
                {
                    cleanWord += std::tolower(c); // 转成小写
                }
            }

            // 5. 过滤停用词和非空单词
            if (!cleanWord.empty() && m_enStopWords.find(cleanWord) == m_enStopWords.end())
            {
                wordCount[cleanWord]++; // 统计词频
            }
        }
        fin.close();
    }

    // 6. 写入词典文件
    std::ofstream fout(outfile);
    int id = 1;
    for (const auto &[word, freq] : wordCount)
    {
        fout << id++ << " " << word << " " << freq << "\n";
    }
    fout.close();

    std::cout << "英文词典生成完成: " << outfile << std::endl;
    std::cout << "词汇总量: " << wordCount.size() << std::endl;
}

// 生成英文索引
void KeywordProcessor::build_en_index(const std::string &dict, const std::string &index)
{
    std::cout << "开始生成英文索引..." << std::endl;

    // 1. 打开词典文件
    std::ifstream fin(dict);
    if (!fin.is_open())
    {
        std::cerr << "错误：无法打开词典文件: " << dict << std::endl;
        return;
    }

    std::string line;
    std::map<char, std::vector<int>> indexMap; // 字母 -> 单词ID列表

    // 2. 逐行读取词典文件
    while (std::getline(fin, line))
    {
        std::istringstream iss(line);
        int id;
        std::string word;

        // 解析每行：ID 单词 频率
        iss >> id >> word;

        if (!word.empty())
        {
            // 3. 取单词首字母作为索引键
            char firstChar = std::tolower(word[0]);

            // 4. 将单词ID加入对应字母的集合
            indexMap[firstChar].push_back(id);
        }
    }
    fin.close();

    // 5. 写入索引文件
    std::ofstream fout(index);
    int lineNumber = 1;

    for (const auto &[ch, ids] : indexMap)
    {
        // 写入格式：行号 字母 ID1 ID2 ID3...
        fout << lineNumber << " " << ch << " ";
        for (int id : ids)
        {
            fout << id << " ";
        }
        fout << "\n";
        lineNumber++;
    }
    fout.close();

    std::cout << "英文索引生成完成: " << index << std::endl;
    std::cout << "索引条目数量: " << indexMap.size() << std::endl;
}

// 生成中文词典
void KeywordProcessor::create_cn_dict(const std::string &dir, const std::string &outfile)
{
    std::cout << "开始生成中文词典..." << std::endl;

    auto files = DirectoryScanner::scan(dir);
    if (files.empty())
    {
        std::cerr << "错误：目录 " << dir << " 中没有找到文件" << std::endl;
        return;
    }

    std::map<std::string, int> wordCount;

    for (const auto &file : files)
    {
        std::ifstream fin(file);
        if (!fin.is_open())
        {
            std::cerr << "无法打开文件: " << file << std::endl;
            continue;
        }

        std::string content((std::istreambuf_iterator<char>(fin)), std::istreambuf_iterator<char>());
        fin.close();

        std::vector<std::string> words;
        m_tokenizer.Cut(content, words);

        for (const auto &word : words)
        {
            // 关键过滤：只保留包含中文字符的词语
            if (!word.empty() &&
                m_chStopWords.find(word) == m_chStopWords.end() &&
                contains_chinese(word)) // 只保留包含中文的词语
            {
                wordCount[word]++;
            }
        }
    }

    // 写入词典文件
    std::ofstream fout(outfile);
    int id = 1;
    for (const auto &[word, freq] : wordCount)
    {
        fout << id << " " << word << " " << freq << "\n";
        id++;
    }
    fout.close();

    std::cout << "中文词典生成完成: " << outfile << std::endl;
    std::cout << "词汇总量: " << wordCount.size() << std::endl;
}

// 辅助函数：检查是否包含中文字符
bool KeywordProcessor::contains_chinese(const std::string &str)
{
    for (unsigned char c : str)
    {
        // 中文字符的UTF-8编码范围
        if (c >= 0xE4 && c <= 0xE9)
        {
            return true;
        }
    }
    return false;
}

// 生成中文索引
void KeywordProcessor::build_cn_index(const std::string &dict, const std::string &index)
{
    std::cout << "开始生成中文索引..." << std::endl;

    // 1. 打开词典文件
    std::ifstream fin(dict);
    if (!fin.is_open())
    {
        std::cerr << "错误：无法打开词典文件: " << dict << std::endl;
        return;
    }

    std::string line;
    std::map<std::string, std::vector<int>> indexMap; // 汉字 -> 词语ID列表

    // 2. 逐行读取词典文件
    while (std::getline(fin, line))
    {
        std::istringstream iss(line);
        int id;
        std::string word;

        // 解析每行：ID 词语 频率
        iss >> id >> word;

        if (!word.empty())
        {
            // 3. 使用utfcpp将词语拆分成单个汉字
            const char *it = word.c_str();
            const char *end = it + word.size();

            while (it < end)
            {
                auto start = it;
                utf8::next(it, end);               // 移动到下一个UTF8字符
                std::string singleChar(start, it); // 提取单个汉字

                // 4. 将词语ID加入对应汉字的集合
                indexMap[singleChar].push_back(id);
            }
        }
    }
    fin.close();

    // 5. 写入索引文件
    std::ofstream fout(index);
    int lineNumber = 1;

    for (const auto &[ch, ids] : indexMap)
    {
        // 写入格式：行号 汉字 ID1 ID2 ID3...
        fout << lineNumber << " " << ch << " ";
        for (int id : ids)
        {
            fout << id << " ";
        }
        fout << "\n";
        lineNumber++;
    }
    fout.close();

    std::cout << "中文索引生成完成: " << index << std::endl;
    std::cout << "索引条目数量: " << indexMap.size() << std::endl;

    // 显示前10个索引条目作为验证
    std::cout << "前10个索引示例:" << std::endl;
    int count = 0;
    for (const auto &[ch, ids] : indexMap)
    {
        if (count++ < 10)
        {
            std::cout << "  " << ch << ": ";
            for (int i = 0; i < std::min(5, (int)ids.size()); i++)
            {
                std::cout << ids[i] << " ";
            }
            if (ids.size() > 5)
                std::cout << "...";
            std::cout << " (共" << ids.size() << "个词)" << std::endl;
        }
    }
}

// 主处理函数 - 整合所有功能
void KeywordProcessor::process(const std::string &chDir, const std::string &enDir)
{
    std::cout << "=== 开始关键字推荐处理 ===" << std::endl;

    // 1. 处理英文语料
    std::cout << "\n--- 处理英文语料 ---" << std::endl;
    create_en_dict(enDir, "output/dict_en.dat");
    build_en_index("output/dict_en.dat", "output/index_en.dat");

    // 2. 处理中文语料
    std::cout << "\n--- 处理中文语料 ---" << std::endl;
    create_cn_dict(chDir, "output/dict_cn.dat");
    build_cn_index("output/dict_cn.dat", "output/index_cn.dat");

    std::cout << "\n=== 关键字推荐处理完成 ===" << std::endl;
    std::cout << "生成的文件：" << std::endl;
    std::cout << "  - output/dict_en.dat    (英文词典)" << std::endl;
    std::cout << "  - output/index_en.dat   (英文索引)" << std::endl;
    std::cout << "  - output/dict_cn.dat    (中文词典)" << std::endl;
    std::cout << "  - output/index_cn.dat   (中文索引)" << std::endl;
}